﻿using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

namespace MapEditor
{
    public class TileMapBuilder : EditorWindow
    {
        SpriteData _sprite_data;
        GridDrawer _grid_drawer;

        /// <summary>
        /// Editor SceneView Settings
        /// </summary>
        static SceneView _scene_view;

        void OnEnable()
        {
            _sprite_data = new SpriteData();
            _grid_drawer = new GridDrawer();

            //SceneView.onSceneGUIDelegate += OnScene;
        }

        void OnDestroy ()
        {
            //SceneView.onSceneGUIDelegate -= OnScene;

            if ( null != _scene_view )
            {
                _scene_view.in2DMode = false;
            }
        }

        private static void OnScene ( SceneView scene_view )
        {
            Handles.BeginGUI();

            if ( GUILayout.Button( "Press me" ) )
                Debug.Log( "Got it to work" );

            Handles.EndGUI();
        }



        void InitUIElements()
        {
            _sprite_data.OnGUI();
            _grid_drawer.OnGUI();
        }

        void OnGUI ()
        {
            InitUIElements();

            //DrawASimpleLine();

            if (null != _sprite_data.spriteRenderer)
            {
                EditorGUI.DrawPreviewTexture( new Rect( 0, 0, _sprite_data.width, _sprite_data.height ),
    _sprite_data.spriteRenderer.sprite.texture );
            }
        }


        #region Customizd Drawing

        void DrawASimpleLine ()
        {
            Handles.BeginGUI();

            Handles.color = Color.red;

            Handles.DrawLine( new Vector3( 0, 0 ), new Vector3( 300, 300 ) );

            Handles.EndGUI();
        }

        #endregion Customized Drawing


        #region MenuItem

        [MenuItem( "Sprite Editor/Init" )]
        public static void ShowWindow ()
        {
            var wnd = (TileMapBuilder) EditorWindow.GetWindow( typeof( TileMapBuilder ) );
            wnd.Show();

            EditorSettings.defaultBehaviorMode = EditorBehaviorMode.Mode2D;

            _scene_view = SceneView.sceneViews[0] as SceneView;
            if ( null != _scene_view )
            {
                _scene_view.in2DMode = true;
            }
        }

        #endregion MenuItem

        #region Style Settings

        static GUILayoutOption[] options = { GUILayout.MaxWidth( 200.0f ), GUILayout.MinWidth( 10.0f ) };

        #endregion Style Settings

        class SpriteData
        {
            SpriteRenderer _sprite_renderer;

            public SpriteRenderer spriteRenderer
            {
                get { return _sprite_renderer; }
                set { _sprite_renderer = value; }
            }

            public int width
            {
                get
                {
                    if ( null != _sprite_renderer && null != _sprite_renderer.sprite )
                    {
                        return _sprite_renderer.sprite.texture.width;
                    }

                    return 0;
                }
            }

            public int height
            {
                get
                {
                    if ( null != _sprite_renderer && null != _sprite_renderer.sprite )
                    {
                        return _sprite_renderer.sprite.texture.height;
                    }

                    return 0;
                }
            }

            public void OnEnable ()
            {
                SceneView.onSceneGUIDelegate += OnScene;
            }

            public void OnGUI()
            {
                var style = new GUIStyle();
                style.normal.background = Texture2D.whiteTexture;


                EditorGUILayout.LabelField( "Basic Information", EditorStyles.boldLabel );

                var obj = EditorGUILayout.ObjectField( "Sprite", spriteRenderer, typeof( SpriteRenderer ), true );
                spriteRenderer = obj as SpriteRenderer;
                //TODO: if the sprite of _sprite_renderer is null, then reset the contents

                EditorGUI.BeginDisabledGroup( null == spriteRenderer );

                EditorGUILayout.BeginHorizontal( style );
                GUILayout.Label( "Width" );
                EditorGUILayout.IntField( spriteRenderer != null ? width : 0 );
                GUILayout.Label( "Height" );
                EditorGUILayout.IntField( spriteRenderer != null ? height : 0 );
                EditorGUILayout.EndHorizontal();

                EditorGUI.EndDisabledGroup();
            }
        }

        class GridDrawer
        {

            private bool showMain = true;
            private bool showSub = false;

            private int gridSizeX;
            private int gridSizeY;
            private int gridSizeZ;

            private float smallStep;
            private float largeStep;

            private float startX;
            private float startY;
            private float startZ;

            private Material lineMaterial;

            private Color mainColor = new Color( 0f, 1f, 0f, 1f );
            private Color subColor = new Color( 0f, 0.5f, 0f, 1f );

            void CreateLineMaterial ()
            {
                if ( !lineMaterial )
                {
                    // Unity has a built-in shader that is useful for drawing
                    // simple colored things.
                    var shader = Shader.Find( "Hidden/Internal-Colored" );
                    lineMaterial = new Material( shader );
                    lineMaterial.hideFlags = HideFlags.HideAndDontSave;
                    // Turn on alpha blending
                    lineMaterial.SetInt( "_SrcBlend", (int) UnityEngine.Rendering.BlendMode.SrcAlpha );
                    lineMaterial.SetInt( "_DstBlend", (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha );
                    // Turn backface culling off
                    lineMaterial.SetInt( "_Cull", (int) UnityEngine.Rendering.CullMode.Off );
                    // Turn off depth writes
                    lineMaterial.SetInt( "_ZWrite", 0 );
                }
            }

            void OnPostRender ()
            {
                CreateLineMaterial();
                // set the current material
                lineMaterial.SetPass( 0 );

                GL.Begin( GL.LINES );

                if ( showSub )
                {
                    GL.Color( subColor );

                    //Layers
                    for ( float j = 0; j <= gridSizeY; j += smallStep )
                    {
                        //X axis lines
                        for ( float i = 0; i <= gridSizeZ; i += smallStep )
                        {
                            GL.Vertex3( startX, startY + j, startZ + i );
                            GL.Vertex3( startX + gridSizeX, startY + j, startZ + i );
                        }

                        //Z axis lines
                        for ( float i = 0; i <= gridSizeX; i += smallStep )
                        {
                            GL.Vertex3( startX + i, startY + j, startZ );
                            GL.Vertex3( startX + i, startY + j, startZ + gridSizeZ );
                        }
                    }

                    //Y axis lines
                    for ( float i = 0; i <= gridSizeZ; i += smallStep )
                    {
                        for ( float k = 0; k <= gridSizeX; k += smallStep )
                        {
                            GL.Vertex3( startX + k, startY, startZ + i );
                            GL.Vertex3( startX + k, startY + gridSizeY, startZ + i );
                        }
                    }
                }

                if ( showMain )
                {
                    GL.Color( mainColor );

                    //Layers
                    for ( float j = 0; j <= gridSizeY; j += largeStep )
                    {
                        //X axis lines
                        for ( float i = 0; i <= gridSizeZ; i += largeStep )
                        {
                            GL.Vertex3( startX, startY + j, startZ + i );
                            GL.Vertex3( startX + gridSizeX, startY + j, startZ + i );
                        }

                        //Z axis lines
                        for ( float i = 0; i <= gridSizeX; i += largeStep )
                        {
                            GL.Vertex3( startX + i, startY + j, startZ );
                            GL.Vertex3( startX + i, startY + j, startZ + gridSizeZ );
                        }
                    }

                    //Y axis lines
                    for ( float i = 0; i <= gridSizeZ; i += largeStep )
                    {
                        for ( float k = 0; k <= gridSizeX; k += largeStep )
                        {
                            GL.Vertex3( startX + k, startY, startZ + i );
                            GL.Vertex3( startX + k, startY + gridSizeY, startZ + i );
                        }
                    }
                }


                GL.End();
            }

            public void OnGUI()
            {
                EditorGUILayout.LabelField( "Grid Settings", EditorStyles.boldLabel );

                showMain = EditorGUILayout.Toggle( "Show Main", showMain );
                showSub = EditorGUILayout.Toggle( "Show Sub", showSub );

                EditorGUILayout.LabelField( "Grid Size" );
                EditorGUILayout.BeginHorizontal();
                GUILayout.Label( "X" );
                gridSizeX = EditorGUILayout.IntField( gridSizeX );
                GUILayout.Label( "Y" );
                gridSizeY = EditorGUILayout.IntField( gridSizeY );
                GUILayout.Label( "Z" );
                gridSizeZ = EditorGUILayout.IntField( gridSizeZ );
                EditorGUILayout.EndHorizontal();


                EditorGUILayout.LabelField( "Steps" );
                EditorGUILayout.BeginHorizontal();
                GUILayout.Label( "Small Step" );
                smallStep = EditorGUILayout.FloatField( smallStep );
                GUILayout.Label( "Large Step" );
                largeStep = EditorGUILayout.FloatField( largeStep );
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.LabelField( "Start Position" );
                EditorGUILayout.BeginHorizontal();
                GUILayout.Label( "X" );
                startX = EditorGUILayout.FloatField( startX );
                GUILayout.Label( "Y" );
                startY = EditorGUILayout.FloatField( startY );
                GUILayout.Label( "Z" );
                startZ = EditorGUILayout.FloatField( startZ );
                EditorGUILayout.EndHorizontal();

                EditorGUILayout.LabelField( "Colors" );
                EditorGUILayout.BeginVertical();
                GUILayout.Label( "Main Color" );
                mainColor = EditorGUILayout.ColorField( mainColor );
                GUILayout.Label( "Sub Color" );
                subColor = EditorGUILayout.ColorField( subColor );
                EditorGUILayout.EndVertical();
            }
        }
    }
}
